%load_ext pretty_jupyter
import pandas as pd
import requests
from utils import *
import plotly.express as px
import plotly.offline as pyo
import matplotlib.pyplot as plt
import seaborn as sns
# Load data from backend API
df_preinclusion = get_data("preinclusion")
df_inclusion = get_data("inclusion")
# Data treatments
# Preinclusion
# 'At risk' status at preinclusion is evaluated using pictograms selected by TBA (no pictograms selected = 'Not at risk')
df_preinclusion['at_risk'] = df_preinclusion.apply(lambda row: True if len(row['pictograms'])>0 else False, axis=1)
df_preinclusion['date'] = pd.to_datetime(df_preinclusion['date'])

# Calculations
total_preinclusions = df_preinclusion.shape[0]
preinclusions_at_risk = df_preinclusion[df_preinclusion['at_risk']==True].shape[0]
preinclusions_at_risk_percentage = round(preinclusions_at_risk/total_preinclusions*100,0)

#Inclusion
df_inclusion['date'] = pd.to_datetime(df_inclusion['date'])
df_inclusion.drop(['lost_qr_code','pregnant','pregnancy_test_result','live_in_study_area','consent','consent_date','date_of_last_period','date_of_last_period_unknown','estimated_date_of_birth','synchronized','created_at','transfered_to',],axis=1,inplace=True)

# Calculations
total_inclusions = df_inclusion.shape[0]
# 'At risk' status at inclusion is evaluated by HW (Yes/No)
inclusions_at_risk = df_inclusion[df_inclusion['pregnancy_at_risk']==1].shape[0]
inclusions_at_risk_percentage = round(inclusions_at_risk/total_inclusions*100,0)
preinclusions_inclusions_percentage = df_inclusion.shape[0]/df_preinclusion.shape[0]*100

Introduction

Wakobo Ti Kodro trial aims to evaluate whether an intervention aimed at birth attendants combining several components (training, use of a mobile app, collaboration with the health system) makes it possible to increase by an absolute difference of at least +10% the proportion of births of pregnant women at risk of obstetric complications in the health structures included in this study after 10 months of intervention.

Data are retrieved on site by Traditionnal Birth Attendants (TBA) or Health workers (HW) using a mobile app (risk factors and warning signs) and by physicians using eCRF.

WaTiKo mobile app's datas are regularly synchronized by site users so they may have a gap between indicators in this dashboard and reality.

Preinclusions

Pregnants womans are preincluded either by Traditionnal Birth Attendants (TBA) or Health workers (HW). 262 women were pre-included in the trial, including 21 with high-risk pregnancy (8.0%).

Figure 1

Cumulative daily preinclusions curve in WaTiKo.

df_fig1 = df_preinclusion.copy()
df_fig1 = df_preinclusion.groupby(pd.Grouper(key='date', freq='D')).size().reset_index(name='number_per_day')
df_fig1['cum_sum'] = df_fig1['number_per_day'].cumsum()
fig1 = px.line(df_fig1, x='date', y='cum_sum')
fig1.update_xaxes(title_text='Days')
fig1.update_yaxes(title_text='Cumulated preinclusions')
fig1.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig1.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig1.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig1.show()

Figure 2

Daily preinclusions in WaTiKo, by status risk.

df_fig2 = df_preinclusion.copy()
df_fig2 = df_fig2.groupby(['date', 'at_risk']).size().reset_index(name='count')
# Renommer les valeurs de 'at_risk' pour rendre le graphique plus lisible
df_fig2['at_risk'] = df_fig2['at_risk'].map({False: 'Not at Risk', True: 'At Risk'})
# Créer l'histogramme avec une couleur spécifique pour 'At Risk'
fig2 = px.bar(df_fig2, x='date', y='count', color='at_risk', labels={'count': 'Number of pregnant womans', 'at_risk': 'Risk Status'},color_discrete_map={'Not at Risk': 'rgb(233,30,99)', 'At Risk': 'rgb(255,178,102)'},category_orders={'pregnancy_at_risk': ['Not at Risk', 'At Risk']})
fig2.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig2.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig2.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig2.show()

Figure 3

Cumulative preinclusions curve in WaTiKo per traditional birth attendants.

df_fig3 = df_preinclusion.copy()
df_fig3['tba'] = df_fig3.apply(lambda row: get_patient_tba(row['qr_code']), axis=1)
df_fig3['site'] = df_fig3.apply(lambda row: get_patient_site(row['qr_code']), axis=1)
df_fig3 = df_fig3.groupby(['tba', 'at_risk']).size().reset_index(name='count')
df_fig3['at_risk'] = df_fig3['at_risk'].map({False: 'Not at Risk', True: 'At Risk'})

fig3 = px.bar(df_fig3, x='tba', y='count', color='at_risk',labels={'count': 'Number pregnant womans', 'at_risk': 'Risk Status'},color_discrete_map={'Not at Risk': 'rgb(233,30,99)', 'At Risk': 'rgb(255,178,102)'},category_orders={'pregnancy_at_risk': ['Not at Risk', 'At Risk']})
fig3.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig3.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig3.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig3.show()

Inclusions

Pregnants womans are exclusively included by Health Workers (HW).

262 women are included in the trial (100.0 % of preincluded womans), including 98 with high-risk pregnancy (37.0%).

Figure 4

Repartition of number of amenorrhea weeks at inclusions in WaTiKo.

fig4 = px.histogram(df_inclusion[['number_of_amenorrhea_weeks']], x="number_of_amenorrhea_weeks",title="",color_discrete_sequence=['rgb(233,30,99)'],)
fig4.update_xaxes(title_text='Number of amenorrhea weeks')
fig4.update_yaxes(title_text='Count')
fig4.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig4.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig4.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig4.show()

Figure 5

Cumulative daily inclusions curve in WaTiKo.

df_fig5 = df_inclusion.copy() 
df_fig5 = df_inclusion.groupby(pd.Grouper(key='date', freq='D')).size().reset_index(name='number_per_day')
df_fig5['cum_sum'] = df_fig5['number_per_day'].cumsum()
fig5 = px.line(df_fig5, x='date', y='cum_sum')
fig5.update_xaxes(title_text='Days')
fig5.update_yaxes(title_text='Cumulated inclusions')
fig5.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig5.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig5.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig5.show()

Figure 6

Daily inclusions in WaTiKo, by status risk.

df_fig6 = df_inclusion.copy()
df_fig6 = df_fig6.groupby(['date', 'pregnancy_at_risk']).size().reset_index(name='count')
df_fig6['At risk status'] = df_fig6['pregnancy_at_risk'].map({0: 'Not at Risk', 1: 'At Risk'})
fig6= px.bar(df_fig6, x='date', y='count', color='At risk status', 
              labels={'count': 'Number of pregnant womans', 'At risk status': 'Risk Status'},
              color_discrete_map={'Not at Risk': 'rgb(233,30,99)', 'At Risk': 'rgb(255,178,102)'},
              category_orders={'At risk status': ['Not at Risk', 'At Risk']},
             )
fig6.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig6.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig6.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig6.show()

Figure 7

Cumulative inclusions curve in WaTiKo per Health Workers.

df_fig7 = df_inclusion.copy()
df_fig7['hw'] = df_fig7.apply(lambda row: get_username(row['created_by']), axis=1)
#df_fig7['site'] = df_fig7.apply(lambda row: get_patient_site(row['qr_code']), axis=1)
df_fig7['pregnancy_at_risk'] = df_fig7['pregnancy_at_risk'].map({0: 'Not at Risk', 1: 'At Risk'})
df_fig7 = df_fig7.groupby(['hw', 'pregnancy_at_risk']).size().reset_index(name='count')

fig7 = px.bar(df_fig7, x='hw', y='count', color='pregnancy_at_risk',labels={'count': 'Number pregnant womans', 'At risk status': 'Risk Status'},color_discrete_map={'Not at Risk': 'rgb(233,30,99)', 'At Risk': 'rgb(255,178,102)'},category_orders={'pregnancy_at_risk': ['Not at Risk', 'At Risk']})
fig7.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig7.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgb(233,30,99)', linecolor='rgb(233,30,99)')
fig7.update_layout(plot_bgcolor='rgba(0,0,0,0)')
fig7.show()

Figure 8

Correlation 'at risk' status between preinclusion and inclusion.

df1 = df_preinclusion.copy()[['uuid','at_risk']]
df1['at_risk'] = df1.apply(lambda row: 1 if row['at_risk'] else 0, axis=1)
df2 = df_inclusion.copy()[['preinclusion','pregnancy_at_risk']]
df = pd.merge(df1,df2, left_on='uuid', right_on='preinclusion', how='outer')
df.rename(columns={"at_risk": "Preinclusion at risk", "pregnancy_at_risk": "Inclusion at risk"},inplace=True)
sns.heatmap(df[["Preinclusion at risk", "Inclusion at risk"]].corr().abs(), cmap="Blues", vmin=0, vmax=1, annot=True)
plt.show()